package com.gobrs.async.core.engine;

import com.gobrs.async.core.GobrsAsync;
import com.gobrs.async.core.GobrsPrint;
import com.gobrs.async.core.common.exception.NotTaskRuleException;
import com.gobrs.async.core.config.ConfigManager;
import com.gobrs.async.core.config.GobrsAsyncProperties;
import com.gobrs.async.core.config.RuleConfig;
import com.gobrs.async.core.holder.BeanHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 通过继承ApplicationListener来达到spring容器启动后自动解析任务配置规则
 */
public class RulePostProcessor implements ApplicationListener<ApplicationReadyEvent> {

    private final Logger logger = LoggerFactory.getLogger(RulePostProcessor.class);

    private ConfigManager configManager;

    private final AtomicBoolean initialized = new AtomicBoolean(false);

    public RulePostProcessor(ConfigManager configManager) {
        this.configManager = configManager;
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        if (initialized.compareAndSet(false, true)) {
            init();
        }
    }

    /**
     * 规则配置解析的入口
     */
    private void init() {
        GobrsAsyncProperties properties = BeanHolder.getBean(GobrsAsyncProperties.class);
        GobrsAsync gobrsAsync = BeanHolder.getBean(GobrsAsync.class);
        List<RuleConfig> rules = properties.getRules();
        Optional.ofNullable(rules).map((data) -> {
            // 解析规则的主要目的是检查规则是否正确 可扩展的任务流解析 推荐:可以使用SPI扩展自定义规则引擎
            try {
                RuleEngine engine = BeanHolder.getBean(RuleEngine.class);
                for (RuleConfig rule : rules) {
                    configManager.addRule(rule.getName(), rule);
                    engine.doParse(rule, false);
                    gobrsAsync.readyTo(rule.getName());
                }
            } catch (Exception exception) {
                logger.error("RulePostProcessor parse error{}", exception);
                throw exception;
            }
            GobrsPrint.printBanner();
            GobrsPrint.getVersion();
            return 1;
        }).orElseThrow(() -> new NotTaskRuleException("com.gobrs.async.rule parse error"));
    }

}
